package com.open.basic.job;


import com.open.basic.exception.BizException;
import com.open.basic.schedule.ScheduleConfig;
import com.open.basic.thread.ThreadPoolUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.config.CronTask;
import org.springframework.scheduling.config.ScheduledTask;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.config.Task;
import org.springframework.scheduling.support.CronExpression;

import javax.annotation.Resource;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadPoolExecutor;


/***
 * @Description: 定时任务配置
 *
 *
 *
 */
@Configuration
@EnableAsync
// public class JobConfig implements SchedulingConfigurer {
public class JobConfig extends ScheduledTaskRegistrar implements CommandLineRunner  {

    private static final Logger log = LoggerFactory.getLogger(JobConfig.class);

    ThreadPoolExecutor threadPoolExecutor = ThreadPoolUtil.getNewThreadPool("job", 10);

    private Map<String, ScheduledTask> taskMap = new ConcurrentHashMap<>();



    /**
     * 添加任务
     *
     * @param job
     */
    public void addTask(BasicJobRunnable job) {
        Objects.requireNonNull(job);
        String cron = job.getBasicTask().getCron();
        job.getBasicTask().setExecuteCount(0);
        boolean validExpression = CronExpression.isValidExpression(cron);
        if (!validExpression) {
            log.error("定时任务【{}】表达式【{}】不合法！", job.getBasicTask().getTaskName(), cron);
            throw new BizException("定时任务表达式不合法！");
        }
        if (taskMap.containsKey(job.getBasicTask().getTaskId())) {
            log.error("任务【{}】已存在！", job.getBasicTask().getTaskName());
            throw new BizException("任务已存在！");
        }
        CronTask cronTask = new CronTask(job, cron);
        ScheduledTask scheduledTask = this.scheduleCronTask(cronTask);
        taskMap.put(job.getBasicTask().getTaskId(), scheduledTask);
        log.info("添加定时任务[{}][{}]成功！", job.getBasicTask().getTaskName(), job.getBasicTask().getCron());
    }

    /**
     * 移除任务
     *
     * @param taskId
     */
    public void removeTask(String taskId) {
        if (!taskMap.containsKey(taskId)) {
            log.warn("任务【{}】不存在, 移除失败", taskId);
            return;
        }
        ScheduledTask scheduledTask = taskMap.remove(taskId);
        if (scheduledTask == null) {
            return;
        }
        Task task = scheduledTask.getTask();
        BasicJobRunnable runnable = (BasicJobRunnable) task.getRunnable();
        String taskName = runnable.getBasicTask().getTaskName();
        log.info("任务【{}, {}】已在执行计划中！移除该任务！", taskId, taskName);
        scheduledTask.cancel();
    }

    // @Override
    // public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
    //     this.taskRegistrar = scheduledTaskRegistrar;
    // }

    @Override
    public void destroy() {
        super.destroy();
        taskMap.values().forEach(ScheduledTask::cancel);
        taskMap.clear();
    }


    @Resource
    ScheduleConfig scheduleConfig;
    /**
     * Callback used to run the bean.
     *
     * @param args incoming main method arguments
     * @throws Exception on error
     */
    @Override
    public void run(final String... args) throws Exception {
        scheduleConfig.configureTasks(this);
    }
}
